【小ネタ】Lambda Layersのパッケージ作成に便利!!pipenvでsync対象ディレクトリを指定する方法
CX事業本部@大阪の岩田です。
Lambda Layers用のパッケージを作成する際にpipenv sync
でライブラリをインストールする対象のディレクトリを指定したかったのですが、それらしきオプションが見つからず色々と試行錯誤していました。最終的にpipの環境変数を使うことでうまく制御できたので手順をご紹介します。
注意!!
こちらの記事で紹介している手順ですが、pipenvのバージョンv2020.5.28からは意図通りに動作しなくなりました。以下のコミットで既にインストール済みのライブラリについてはインストール処理をスキップする最適化処理が追加されたのですが、この処理では常にデフォルトのディレクトリ(.venv/lib/python3.x/site-packages/ 等)をチェックしてライブラリがインストール済みかを判定しています。そのため、デフォルトのディレクトリにライブラリがインストールされた状態で、デフォルト以外のディレクトリに別途ライブラリをインストールしようとしても、インストールがスキップされてしまうのです。
Skip satisfied dependencies during installation
ライブラリがインストール済みかを判定する際に環境変数PIP_TARGET
を考慮するよう修正するプルリクを上げているので、これがマージされれば以前のバージョンと同じ感覚で利用できるようになるはずです。
https://github.com/pypa/pipenv/pull/4776
pipenvでsync対象ディレクトリを指定する方法
まず結論から
PIP_TARGET="<targetdir>" pipenv sync
これで<targetdir>
ディレクトリ配下にPipfile.lockで定義されたライブラリがインストールできます。
あとはZIPに固めてアップロードすれば必要なライブラリが導入されたLambda Layerの完成です!
ググるとpipenv lock -r | pip install -r /dev/stdin -t <targetdir>
でイケるぜ!!みたいな記事がいくつかヒットしたのですが、これだと都度都度Pipfile.lockの更新が走ってしまうので、導入対象ライブラリが依存しているライブラリが開発環境とは異なるバージョンでインストールされるというリスクが残ります。
開発環境で仮想環境をアクティベートしてpipenv run pip freeze| pip install -r /dev/stdin -t <targetdir>
を実行するのもアリですが、これだと余計なdevパッケージまでインストールされてしまいます。
pipの環境変数について
pipのUser Guideに記載があるのですが、pipのコマンドラインオプションは環境変数から指定することが可能です。設定すべき環境変数はpipのコマンドラインのロングオプションを
- 大文字に変換する
-
を_
に変換する- 先頭に
PIP_
をつける
というルールで変換したものです。
pip’s command line options can be set with environment variables using the format `PIP_
` . Dashes (`-`) have to be replaced with underscores (`_`).
例えばPIP_TARGET=<targetdir> pip install
というコマンドはpip install --target <targetdir>
と同様の挙動となります。pipenv sync
は内部的にpip install
を実行するためPIP_TARGET=<targetdir> pipenv sync
というコマンドはpipenv install --requirement <Pipfile.lockで定義されたライブラリ達> --target <targetdir>
を実行することになり、Pipfile.lockで定義されたライブラリを指定したディレクトリにインストールすることが可能です。
まとめ
これで開発環境と同一バージョンのライブラリでLayerが作成可能です。 開発環境とLambda実行環境でライブラリのバージョンが違ってバグを踏んだ...なんてことがないように有効活用していきましょう